/*************************************************************************************
*Copyright (c) 2011, Intel Mobile Communications GmbH. 
*All rights reserved.
*
*Redistribution and use in source and binary forms, with or without
*modification, are permitted provided that the following conditions are met:
*    * Redistributions of source code must retain the above copyright
*      notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright
*      notice, this list of conditions and the following disclaimer in the
*      documentation and/or other materials provided with the distribution.
*    * Neither the name of the <organization> nor the
*      names of its contributors may be used to endorse or promote products
*      derived from this software without specific prior written permission.
*
*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
*ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*DISCLAIMED. IN NO EVENT SHALL INTEL MOBILE COMMUNICATIONS GMBH. BE LIABLE FOR ANY
*DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
*(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************************/



#ifndef CEF_BLOCK_H
#define CEF_BLOCK_H
#include <string>
#include <vector>
#ifdef _DEBUG
#include <iostream>
#endif
enum cef_port_protocol {OCP,AHB,AXI,NOC};
enum cef_protocol_var {DATAHANDSHAKE,NOBURST,NONE}; 
enum cef_degree_orientation{ d0=0,d90=90,d180=180,d270=270};

class cef_connection
{
	protected:
	std::string name;	
	unsigned id;
	unsigned type;
	public:
	cef_connection();
	cef_connection(unsigned,std::string,unsigned);
	~cef_connection();
	//Setters
	void setName(std::string);
	void setID(unsigned);
	void setType(unsigned);
	//Getters
	std::string getName();
	unsigned getID();
	unsigned getType();
#ifdef _DEBUG	
	void print();	
#endif
	
};

class cef_port
{
	protected:	
	unsigned id;
	std::string protocol;
	std::string protocol_variant;
	unsigned max_outstanding_transactions;
	unsigned address_width;
	unsigned read_data_width;
	unsigned write_data_width;
	unsigned flit_width;
	std::pair<double,double>* position;
	unsigned domain_id;
		
	public:
	cef_port();
	cef_port(unsigned,std::string,std::string,unsigned, unsigned,unsigned,unsigned,unsigned, std::pair<double,double>*, unsigned);
	~cef_port();
	//Setters
	void setID(unsigned);
	void setMOT(unsigned);
	void setAddressWidth(unsigned);
	void setReadDataWidth(unsigned);
	void setWriteDataWidth(unsigned);
	void setFlitWidth(unsigned);
	void setPosition(std::pair<double,double>*);
	void setDomainID(unsigned);
	void setProtocol(std::string);
	void setProtocolVar(std::string);
	//Getters
	unsigned getID();
	unsigned getMOT();
	unsigned getAddressWidth();
	unsigned getReadDataWidth();
	unsigned getWriteDataWidth();
	unsigned getFlitWidth();
	std::string getProtocol();
	std::string getProtocolVar();
	std::pair<double,double>* getPosition();
	unsigned getDomainID();
#ifdef _DEBUG	
	void print();	
#endif
};

class cef_block_blc_pos//Bottom left corner position
{
	protected:	
	double x,y;
	double initialx,initialy;
	bool movable;	
	public:
	cef_block_blc_pos();
	cef_block_blc_pos(double,double,double,double,bool);
	~cef_block_blc_pos();
	//Setters
	void setX(double);
	void setY(double);
	void setInitX(double);
	void setInitY(double);
	void setMove(bool);
	//Getters
	double getX();
	double getY();
	double getInitX();
	double getInitY();
	bool getMove();
#ifdef _DEBUG	
	void print();	
#endif
};

class cef_block_size
{
	protected:
	bool soft;
	std::vector<std::pair<double,double>*>* shape;
	double area;
	double aspect_ratio;
	public:
	cef_block_size();
	cef_block_size(bool,std::vector<std::pair<double,double>*>*,double,double);
	~cef_block_size();
	//Setters
	void setSoft(bool);
	void setShape(std::vector<std::pair<double,double>* >*);
	void setArea(double);
	void setAspectRatio(double);
	//Getters
	bool getSoft();
	std::vector<std::pair<double,double>* >* getShape();
	double getArea();
	double getAspectRatio();
#ifdef _DEBUG	
	void print();	
#endif
};

class cef_block_orientation
{
	protected:
	bool rotatable;
	bool mirrorable;
	cef_degree_orientation rotation;
	cef_degree_orientation initial_rotation;
	bool mirroringx;
	bool initial_mirroringx;
	bool mirroringy;
	bool initial_mirroringy;	
	public:
	cef_block_orientation();
	cef_block_orientation(bool,bool,cef_degree_orientation,cef_degree_orientation,bool,bool,bool,bool);
	~cef_block_orientation();
	//Setters
	void setRotate(bool);
	void setMirror(bool);
	void setRotation(cef_degree_orientation);
	void setInitRotation(cef_degree_orientation);
	void setMirroringX(bool);
	void setInitMirroringX(bool);
	void setMirroringY(bool);
	void setInitMirroringY(bool);
	//Getters
	bool getRotate();
	bool getMirror();
	cef_degree_orientation getRotation();
	cef_degree_orientation getInitRotation();
	bool getMirroringX();
	bool getInitMirroringX();
	bool getMirroringY();
	bool getInitMirroringY();
	//DEBUG
#ifdef _DEBUG	
	void print();	
#endif
};

class cef_block_architecture
{
	protected:
	std::string type;
	std::vector<std::pair<unsigned long long, unsigned long long>* >* address_ranges;// (start,size)
	std::vector<unsigned>* inbuffer;//depths of inbuffers
	std::vector<unsigned>* outbuffer;//depths of outbuffers
	unsigned virtual_channels;
	std::string vc_arbitration;
	std::string arbitration_policy;
	std::string vc_struct;
	public:
	cef_block_architecture();
	cef_block_architecture(std::string,std::vector<std::pair<unsigned long long,unsigned long long>* >*, std::vector<unsigned>*,std::vector<unsigned>*,unsigned,std::string,std::string,std::string); 
	~cef_block_architecture();
	//Setters
	void setNIType(std::string);
	void setAddrRngs(std::vector<std::pair<unsigned long long, unsigned long long>* >*);
	void setInBuffers(std::vector<unsigned>*);
	void setOutBuffers(std::vector<unsigned>*);
	void setVCs(unsigned);
	void setVCArbStruct(std::string);
	void setVCArbit(std::string);
	void setArbit(std::string);
	//Getters
	std::string getNIType();
	std::vector<std::pair<unsigned long long, unsigned long long>* >* getAddrRngs();
	std::vector<unsigned>* getInBuffers();
	std::vector<unsigned>*  getOutBuffers();
	unsigned getVCs();
	std::string getVCArbStruct();
	std::string getVCArbit();
	std::string getArbit();
#ifdef _DEBUG	
	void print();	
#endif
};

class cef_block
{
	protected:
	std::string name;	
	unsigned id;
	unsigned type;
	std::vector<unsigned>* connections;	
	cef_block_size* size;
	cef_block_orientation* orientation;
	cef_block_blc_pos* bottomleftcorner_position;
	std::vector<cef_port*>* ports;
	unsigned layer;
	//unsigned domainid;
	cef_block_architecture* architecture;
	public:
	cef_block();
	cef_block(unsigned,std::string,unsigned,std::vector<unsigned>*, std::vector<cef_port*>* ,cef_block_size*, cef_block_orientation*, cef_block_blc_pos*,unsigned, cef_block_architecture*);
	~cef_block();
	//Setters
	void setID(unsigned);
	void setType(unsigned);
	void setName(std::string);
	void setConnections(std::vector<unsigned>*);
	void setSize(cef_block_size*);
	void setOrientation(cef_block_orientation*);
	void setBotLefCor(cef_block_blc_pos*);
	void setLayer(unsigned);
	void setPorts(std::vector<cef_port*>*);
	void setArchitecture(cef_block_architecture*);
	//Getters
	unsigned getID();
	unsigned getType();
	std::string getName();
	std::vector<unsigned>* getConnections();
	std::vector<cef_port*>* getPorts();
	cef_block_size* getSize();
	cef_block_orientation* getOrientation();
	cef_block_blc_pos* getBotLefCor();
	unsigned getLayer();
	cef_block_architecture* getArchitecture();
#ifdef _DEBUG	
	void print();	
#endif
};
#endif
